package org.jeecg.modules.kuner.viporderbase.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.wechat.pay.java.service.payments.jsapi.model.PrepayWithRequestPaymentResponse;
import org.jeecg.common.constant.CommonConstant;
import org.jeecg.common.exception.JeecgBootException;
import org.jeecg.common.util.Strings;
import org.jeecg.common.util.pay.vo.CcWxPayOrderVO;
import org.jeecg.common.util.pay.wx.WxPayUtil;
import org.jeecg.modules.kuner.sysconf.SysConfigService;
import org.jeecg.modules.kuner.userpointstatement.service.ISdUserPointStatementService;
import org.jeecg.modules.kuner.userrec.entity.UserRecShip;
import org.jeecg.modules.kuner.userrec.service.IUserRecShipService;
import org.jeecg.modules.kuner.useruimestatement.service.IKrUserTimeStatementService;
import org.jeecg.modules.kuner.vipgoodbase.entity.KrVipGoodBase;
import org.jeecg.modules.kuner.vipgoodbase.service.IKrVipGoodBaseService;
import org.jeecg.modules.kuner.vipgoodusertime.service.IKrGoodUserTimeService;
import org.jeecg.modules.kuner.viporderbase.entity.KrVipOrderBase;
import org.jeecg.modules.kuner.viporderbase.mapper.KrVipOrderBaseMapper;
import org.jeecg.modules.kuner.viporderbase.service.IKrVipOrderBaseService;
import org.jeecg.modules.kuner.viporderbase.vo.PlaceOrderVO;
import org.jeecg.modules.putil.KrStatic;
import org.jeecg.modules.putil.LoginUserUtil;
import org.jeecg.modules.system.entity.SysUser;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.Optional;

/**
 * @Description: 会员订单
 * @Author: jeecg-boot
 * @Date: 2025-02-19
 * @Version: V1.0
 */
@Service
public class KrVipOrderBaseServiceImpl extends ServiceImpl<KrVipOrderBaseMapper, KrVipOrderBase> implements IKrVipOrderBaseService {

    @Resource
    @Lazy
    private IKrVipOrderBaseService vipOrderBaseService;
    @Resource
    private IKrUserTimeStatementService userTimeStatementService;
    @Resource
    private IKrGoodUserTimeService goodUserTimeService;
    @Resource
    private IKrVipGoodBaseService vipGoodBaseService;
    @Resource
    private LoginUserUtil loginUserUtil;
    @Resource
    private WxPayUtil wxPayUtil;
    @Resource
    private ISdUserPointStatementService userPointStatementService;
    @Resource
    private SysConfigService sysConfigService;
    @Resource
    private IUserRecShipService userRecShipService;

    /**
     * 下单
     *
     * @param placeOrderVO 下单必要参数信息
     * @return 下单结果
     */
    @Override
    public KrVipOrderBase placeOrder(PlaceOrderVO placeOrderVO) {
        SysUser loginUserByDB = loginUserUtil.getLoginUserByDB();
        if (!loginUserByDB.getId().equals(placeOrderVO.getUserId())) {
            throw new JeecgBootException("下单人与登录用户不符！");
        }
        KrVipOrderBase notPayedOrder = checkNotPayedOrder(placeOrderVO.getUserId());
        if (notPayedOrder != null) {
            return notPayedOrder;
        }
        KrVipGoodBase krVipGoodBase = vipGoodBaseService.getOptById(placeOrderVO.getGoodId()).orElseThrow(() -> new JeecgBootException("找不到对应的商品信息！"));
        KrVipOrderBase krVipOrderBase = buildFullOrder(loginUserByDB, krVipGoodBase);
        save(krVipOrderBase);
        return krVipOrderBase;
    }

    /**
     * 取消订单
     *
     * @param orderId 被取消的订单ID
     */
    @Override
    public void cancelOrder(String orderId) {
        KrVipOrderBase krVipOrderBase = getOptById(orderId).orElseThrow(() -> new JeecgBootException("找不到对应的订单信息！"));
        if (!KrStatic.OrderStatus.NOT.equals(krVipOrderBase.getOrderStatus())) {
            throw new JeecgBootException("该订单状态已不允许取消！");
        }
        krVipOrderBase.setOrderStatus(KrStatic.OrderStatus.CANCEL);
        updateById(krVipOrderBase);
    }

    /**
     * 拉起微信小程序支付
     *
     * @param orderId 订单ID
     * @return 支付必要的参数信息
     */
    @Override
    public PrepayWithRequestPaymentResponse toPay(String orderId) {
        KrVipOrderBase krVipOrderBase = getOptById(orderId).orElseThrow(() -> new JeecgBootException("找不到对应的订单信息！"));
        SysUser loginUserByDB = loginUserUtil.getLoginUserByDB();
        if (!loginUserByDB.getId().equals(krVipOrderBase.getUserId())) {
            throw new JeecgBootException("下单用户与支付用户不符！");
        }
        if (!KrStatic.OrderStatus.NOT.equals(krVipOrderBase.getOrderStatus())) {
            throw new JeecgBootException("订单状态异常！");
        }
        CcWxPayOrderVO wxPayOrderVO = buildWxPayOrder(krVipOrderBase, loginUserByDB);
        return wxPayUtil.createPayOrder(wxPayOrderVO);
    }

    /**
     * 支付成功后续业务
     *
     * @param orderNo 订单号
     */
    @Transactional
    @Override
    public void paySuccessLogic(String orderNo) {
        KrVipOrderBase optByOrderNo = getOptByOrderNo(orderNo);
        if (!KrStatic.OrderStatus.NOT.equals(optByOrderNo.getOrderStatus())) {
            throw new JeecgBootException("订单状态异常！");
        }
        String userId = optByOrderNo.getUserId();
        String goodId = optByOrderNo.getGoodId();
        KrVipGoodBase krVipGoodBase = vipGoodBaseService.getOptById(goodId).orElseThrow(() -> new JeecgBootException("找不到对应的商品信息！"));
        userTimeStatementService.modifyUserTime(userId, krVipGoodBase.getTimes(), CommonConstant.TIME_MODIFY_ADD_CHARGE);
        goodUserTimeService.createKr(userId,goodId);
        UserRecShip userMasterInfo = userRecShipService.getUserMasterInfo(userId);
        if (userMasterInfo != null) {
            BigDecimal money = optByOrderNo.getMoney();
            userPointStatementService.userModifyPoint(sysConfigService.getOrderIncomeRate().multiply(money), CommonConstant.POINT_MODIFY_MSG_ORDER_INCOME, optByOrderNo.getUserId());
        }
    }

    /**
     * 根据订单号获取订单信息
     *
     * @param orderNo 订单号
     * @return 找到的订单信息
     */
    public KrVipOrderBase getOptByOrderNo(String orderNo) {
        return Optional.ofNullable(getByOrderNo(orderNo)).orElseThrow(() -> new JeecgBootException("无法根据订单号找到对应的订单信息！"));
    }

    /**
     * 根据订单号获取订单信息
     *
     * @param orderNo 订单号
     * @return 查询结果
     */
    @Override
    public KrVipOrderBase getByOrderNo(String orderNo) {
        return getOne(new LambdaQueryWrapper<KrVipOrderBase>().eq(KrVipOrderBase::getOrderNo, orderNo));
    }

    /**
     * 构建微信支付订单
     *
     * @param vipOrderBase 订单信息
     * @param sysUser      用户信息
     * @return 构建结果
     */
    private CcWxPayOrderVO buildWxPayOrder(KrVipOrderBase vipOrderBase, SysUser sysUser) {
        CcWxPayOrderVO wxPayOrderVO = new CcWxPayOrderVO();
        wxPayOrderVO.setPayAmount(vipOrderBase.getMoney());
        wxPayOrderVO.setMemberId(sysUser.getId());
        wxPayOrderVO.setOpenId(sysUser.getOpenId());
        wxPayOrderVO.setMemberId(sysUser.getId());
        wxPayOrderVO.setOrderNo(vipOrderBase.getOrderNo());
        return wxPayOrderVO;
    }

    /**
     * 校验任意一个未支付的订单信息
     *
     * @param userId 用户信息
     * @return 查询结果
     */
    private KrVipOrderBase checkNotPayedOrder(String userId) {
        return list(new LambdaQueryWrapper<KrVipOrderBase>().eq(KrVipOrderBase::getUserId, userId).eq(KrVipOrderBase::getOrderStatus, KrStatic.OrderStatus.NOT)).stream().findAny().orElse(null);
    }


    /**
     * 构建完整的订单信息
     *
     * @param sysUser       用户信息
     * @param krVipGoodBase 下单商品信息
     * @return 下单结果
     */
    private KrVipOrderBase buildFullOrder(SysUser sysUser, KrVipGoodBase krVipGoodBase) {
        KrVipOrderBase vipOrderBase = new KrVipOrderBase();
        vipOrderBase.setUserName(sysUser.getRealname());
        vipOrderBase.setMoney(krVipGoodBase.getPrice());
        vipOrderBase.setGoodId(krVipGoodBase.getId());
        vipOrderBase.setUserId(sysUser.getId());
        vipOrderBase.setGoodName(krVipGoodBase.getGoodName());
        vipOrderBase.setOrderNo(Strings.generateOrderNo());
        return vipOrderBase;
    }
}
